package org.duang.core;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.duang.aop.ProxyManager;
import org.duang.common.exceptios.ServiceException;
import org.duang.config.Config;
import org.duang.config.InstanceFactory;
import org.duang.db.mongo.MongoDao;
import org.duang.db.sql.SqlDao;
import org.duang.ioc.Import;
import org.duang.kit.BeanKit;
import org.duang.kit.MongoKit;
import org.duang.kit.SqlKit;

public final class IocHepler {

	public static void init() {
		try {
			injectClass(); // 注入Service, Dao到Service层
		} catch (ServiceException se) {
			throw new ServiceException().setMessage(se.getMessage());
		} catch (Exception e) {
			throw new ServiceException(e.getMessage(), e);
		}
	}

	public static void injectService2Controller(Controller controller, Class<? extends Controller> controllerClass) throws Exception {
		Field[] fields = controllerClass.getDeclaredFields();
		List<Class<? extends Annotation>> importAnnotList = InstanceFactory.getImportAnnot();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			for(Class<? extends Annotation> ann : importAnnotList){
				if (null != field && field.isAnnotationPresent(ann)) {
					Object serviceObj = BeanKit.getBean(field.getType());
					if (null == serviceObj) {
						Class<?> cls = field.getType();
						serviceObj = (Object)ProxyManager.newProxyInstance(cls);
						BeanKit.setBean(cls, serviceObj);
					}
					if(null == serviceObj) {
						throw new NullPointerException(field.getType() +" is not exist BeanKit Map");
					}
					field.setAccessible(true);
					field.set(controller, serviceObj);
				}	
			}
		}
	}

	private static void injectClass() throws ServiceException, Exception {
		String SERVICE_FLAG_NAME = StringUtils.split(Config.SERVICE_ENDWITH_NAME, ".")[0];
		String DAO_FLAG_NAME = StringUtils.split(Config.DAO_ENDWITH_NAME, ".")[0];
		boolean isCGLibProxy = Config.isEnableDRL();
		List<Class<? extends Annotation>> importAnnotList = InstanceFactory.getImportAnnot();
		for (Iterator<Entry<Class<?>, Object>> it = BeanKit.getBeanMap().entrySet().iterator(); it.hasNext();) {
			Entry<Class<?>, Object> entry = it.next();
			Object serviceObj = entry.getValue();
			Class<?> serviceClass = entry.getKey();
			Field[] fields = serviceClass.getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				Field field = fields[i];
				for(Class<? extends Annotation> ann : importAnnotList){
					if (null != field && field.isAnnotationPresent(ann)) {
						String fieldName = field.getName();
						if (fieldName.endsWith(SERVICE_FLAG_NAME)) {						
							if (field.getType().equals(serviceClass)) {
								throw new ServiceException()
										.setMessage(serviceClass.getSimpleName() + " Can't Not Import From already!");
							}
							field.setAccessible(true);
							field.set(serviceObj, BeanKit.getBean(serviceObj, field.getType()));
						}
						if (fieldName.endsWith(DAO_FLAG_NAME)) {
							ParameterizedType paramType = (ParameterizedType) field.getGenericType();
							Type[] types = paramType.getActualTypeArguments();
	
							Class<?> paramTypeClazz = Class.forName(types[0].toString().substring(6).trim());
							Class<?> typeClazz = field.getType();
							Object daoObj = null;
	
							if (typeClazz.equals(MongoDao.class)) {
								daoObj = isCGLibProxy ? MongoKit.getProxyDao(paramTypeClazz) : MongoKit.get(paramTypeClazz);
	//							daoObj =  MongoKit.get(paramTypeClazz);
							}
							if (typeClazz.equals(SqlDao.class)) {
								daoObj = isCGLibProxy ? SqlKit.getProxyDao(paramTypeClazz) : SqlKit.get(paramTypeClazz);
							}
							field.setAccessible(true);
							field.set(serviceObj, daoObj);
						}
					}
				}
			}
		}
	}

}
